package com.cch.cooperation.api.zone.service;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cch.cooperation.api.auth.service.UserServiceImpl;
import com.cch.cooperation.api.support.dto.PushAppNoticeDTO;
import com.cch.cooperation.api.support.service.PushServiceImpl;
import com.cch.cooperation.api.zone.dto.ZoneUserApplyAuditDTO;
import com.cch.cooperation.api.zone.dto.ZoneUserApplyDTO;
import com.cch.cooperation.api.zone.dto.ZoneUserApplyJoinDTO;
import com.cch.cooperation.biz.common.lock.Locker;
import com.cch.cooperation.biz.common.util.BeanUtilEx;
import com.cch.cooperation.common.exception.BizException;
import com.cch.cooperation.common.util.SnowflakeIdUtil;
import com.cch.cooperation.dao.auth.model.User;
import com.cch.cooperation.dao.zone.dto.ZoneDTO;
import com.cch.cooperation.dao.zone.dto.ZoneUserDTO;
import com.cch.cooperation.dao.zone.enums.ZoneUserApplyEnum;
import com.cch.cooperation.dao.zone.enums.ZoneUserEnum;
import com.cch.cooperation.dao.zone.mapper.ZoneUserApplyMapper;
import com.cch.cooperation.dao.zone.model.Zone;
import com.cch.cooperation.dao.zone.model.ZoneUserApply;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 空间用户申请业务处理
 *
 * @author cch
 */
@Service
public class ZoneUserApplyServiceImpl {

    @Resource
    private ZoneUserApplyMapper mapper;
    @Resource
    private ZoneServiceImpl zoneService;
    @Resource
    private ZoneUserServiceImpl zoneUserService;
    @Resource
    private UserServiceImpl userService;
    @Resource
    private PushServiceImpl pushService;

    public List<ZoneUserApplyDTO> queryUserList(String userId, String zoneId) {
        if (StrUtil.isEmpty(userId)) {
            throw new BizException("用户id不能为空");
        }
        // 查询对应空间的申请
        LambdaQueryWrapper<ZoneUserApply> query = new LambdaQueryWrapper<>();
        query.eq(ZoneUserApply::getZoneId, zoneId);
        query.orderByAsc(ZoneUserApply::getStatus);
        query.orderByDesc(ZoneUserApply::getCreateTime);
        List<ZoneUserApply> list = mapper.selectList(query);
        List<ZoneUserApplyDTO> result = BeanUtilEx.copy(list, ZoneUserApplyDTO.class);
        // 查询关联用户信息
        Map<String, User> userMap = userService.getMapByIds(result.stream().map(o -> o.getUserId()).distinct().collect(Collectors.toList()));
        // 聚合关联信息
        for (ZoneUserApplyDTO item : result) {
            item.setUser(userMap.get(item.getUserId()));
        }
        return result;
    }

    public Integer getWaitAuditCount(String zoneId) {
        LambdaQueryWrapper<ZoneUserApply> query = new LambdaQueryWrapper<>();
        query.eq(ZoneUserApply::getZoneId, zoneId);
        query.eq(ZoneUserApply::getStatus, ZoneUserApplyEnum.Status.WAITE_AUDIT.value);
        return  mapper.selectCount(query);
    }

    public void join(@Valid ZoneUserApplyJoinDTO req) {
        ZoneDTO zone = zoneService.getByJoinCode(req.getJoinCode());
        if (ObjectUtil.isNull(zone)) {
            throw new BizException("该空间已不存在");
        }
        if (zone.getUsers().stream().anyMatch(o -> o.getId().equals(req.getUserId()))) {
            throw new BizException("您已在该空间中");
        }
        User user = userService.getById(req.getUserId());
        if (Objects.isNull(user)) {
            throw new BizException("当前用户不存在");
        }
        LambdaQueryWrapper<ZoneUserApply> query = new LambdaQueryWrapper<>();
        query.eq(ZoneUserApply::getZoneId, zone.getId());
        query.eq(ZoneUserApply::getUserId, req.getUserId());
        query.eq(ZoneUserApply::getStatus, ZoneUserApplyEnum.Status.WAITE_AUDIT.value);
        query.last("limit 1");
        ZoneUserApply oldApply = mapper.selectOne(query);
        if (Objects.nonNull(oldApply)) {
            oldApply.setRemark(req.getRemark());
            mapper.updateById(oldApply);
            return;
        }
        ZoneUserApply apply = BeanUtilEx.copy(req, ZoneUserApply.class);
        apply.setId(SnowflakeIdUtil.getIdStr());
        apply.setZoneId(zone.getId());
        apply.setStatus(ZoneUserApplyEnum.Status.WAITE_AUDIT.value);
        apply.setCreateTime(new Date());
        mapper.insert(apply);
        // 加入申请空间通知
        PushAppNoticeDTO pushReq = new PushAppNoticeDTO();
        pushReq.setId(apply.getId());
        pushReq.setTitle("星球申请");
        pushReq.setBody(user.getNickname() + "申请加入" + zone.getName() + "星球");
        pushReq.setUrl("td://zone/apply?zoneId='"+ apply.getZoneId() +"'");
        ZoneUserDTO zoneOwner = zoneUserService.queryList(zone.getId()).stream().filter(o -> ZoneUserEnum.RoleType.ADMIN.value.equals(o.getRoleType())).findFirst().orElse(null);
        pushReq.setUserId(zoneOwner.getId());
        pushService.pushAppNotice(pushReq);
    }

    @Locker(key = "'LOCK:ZONE_USER_APPLY:AUDIT'+ #req.id")
    @Transactional(rollbackFor = Exception.class)
    public void audit(@Valid ZoneUserApplyAuditDTO req) {
        ZoneUserApply apply = mapper.selectById(req.getId());
        if (ObjectUtil.isNull(apply) || !ZoneUserApplyEnum.Status.WAITE_AUDIT.value.equals(apply.getStatus())) {
            throw new BizException("该申请已不存在");
        }
        Zone zone = zoneService.getById(apply.getZoneId());
        if (Objects.isNull(zone)) {
            throw new BizException("该空间已不存在");
        }
        // 申请处理
        apply.setStatus(req.getStatus());
        apply.setAuditTime(new Date());
        mapper.updateById(apply);
        // 审核通过添加空间用户
        PushAppNoticeDTO pushReq = new PushAppNoticeDTO();
        pushReq.setId(apply.getId());
        pushReq.setTitle("星球申请");
        pushReq.setUserId(apply.getUserId());
        if (ZoneUserApplyEnum.Status.PASS.value.equals(req.getStatus())) {
            zoneUserService.add(apply.getZoneId(), apply.getUserId(), ZoneUserEnum.RoleType.NORMAL.value);
            pushReq.setBody("您已加入" + zone.getName() + "星球，祝您旅途愉快~");
            pushReq.setUrl("td://zone/apply/resultSuccess");
        } else {
            pushReq.setBody("不好意思" + zone.getName() + "星球未通过您的申请");
        }
        pushService.pushAppNotice(pushReq);
    }



}
